From f9601cd2f64ad6d2af425baccb871e65cdac868a Mon Sep 17 00:00:00 2001 From: Carl Lerche + Yehuda Katz Date: Thu, 12 Jun 2014 17:49:10 -0700 Subject: [PATCH] Allow multiple and non-default crate_types Note that at present there is no good error handling for fat-fingering the crate type. This is a TODO. --- src/cargo/core/manifest.rs | 57 +++++++++++++++++++++++++++------ src/cargo/ops/cargo_rustc.rs | 28 +++++++++------- src/cargo/sources/git/source.rs | 1 + src/cargo/util/toml.rs | 5 ++- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index d5d459c6b..6b9d1b57b 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -1,3 +1,4 @@ +use std::result; use std::fmt; use std::fmt::{Show,Formatter}; use semver::Version; @@ -9,6 +10,7 @@ use core::{ Summary }; use core::dependency::SerializedDependency; +use util::{CargoResult,simple_human}; #[deriving(PartialEq,Clone)] pub struct Manifest { @@ -48,9 +50,42 @@ impl> Encodable for Manifest { } } +#[deriving(Show,Clone,PartialEq,Encodable)] +pub enum LibKind { + Lib, + Rlib, + Dylib, + StaticLib +} + +impl LibKind { + pub fn from_str(string: &str) -> CargoResult { + match string { + "lib" => Ok(Lib), + "rlib" => Ok(Rlib), + "dylib" => Ok(Dylib), + "staticlib" => Ok(StaticLib), + _ => Err(simple_human(format!("{} was not one of lib|rlib|dylib|staticlib", string))) + } + } + + pub fn from_strs(strings: Vec) -> CargoResult> { + result::collect(strings.iter().map(|s| LibKind::from_str(s.as_slice()))) + } + + pub fn crate_type(&self) -> &'static str { + match *self { + Lib => "lib", + Rlib => "rlib", + Dylib => "dylib", + StaticLib => "staticlib" + } + } +} + #[deriving(Show,Clone,PartialEq,Encodable)] pub enum TargetKind { - LibTarget, + LibTarget(Vec), BinTarget } @@ -63,7 +98,7 @@ pub struct Target { #[deriving(Encodable)] pub struct SerializedTarget { - kind: &'static str, + kind: Vec<&'static str>, name: String, path: String } @@ -71,8 +106,8 @@ pub struct SerializedTarget { impl> Encodable for Target { fn encode(&self, s: &mut S) -> Result<(), E> { let kind = match self.kind { - LibTarget => "lib", - BinTarget => "bin" + LibTarget(ref kinds) => kinds.iter().map(|k| k.crate_type()).collect(), + BinTarget => vec!("bin") }; SerializedTarget { @@ -138,9 +173,9 @@ impl Manifest { } impl Target { - pub fn lib_target(name: &str, path: &Path) -> Target { + pub fn lib_target(name: &str, crate_targets: Vec, path: &Path) -> Target { Target { - kind: LibTarget, + kind: LibTarget(crate_targets), name: name.to_str(), path: path.clone() } @@ -160,7 +195,7 @@ impl Target { pub fn is_lib(&self) -> bool { match self.kind { - LibTarget => true, + LibTarget(_) => true, _ => false } } @@ -172,10 +207,12 @@ impl Target { } } - pub fn rustc_crate_type(&self) -> &'static str { + pub fn rustc_crate_types(&self) -> Vec<&'static str> { match self.kind { - LibTarget => "lib", - BinTarget => "bin" + LibTarget(ref kinds) => { + kinds.iter().map(|kind| kind.crate_type()).collect() + }, + BinTarget => vec!("bin") } } } diff --git a/src/cargo/ops/cargo_rustc.rs b/src/cargo/ops/cargo_rustc.rs index 957302f7d..2d38610c5 100644 --- a/src/cargo/ops/cargo_rustc.rs +++ b/src/cargo/ops/cargo_rustc.rs @@ -52,23 +52,29 @@ fn mk_target(target: &Path) -> CargoResult<()> { } fn rustc(root: &Path, target: &Target, dest: &Path, deps: &Path, verbose: bool) -> CargoResult<()> { - log!(5, "root={}; target={}; dest={}; deps={}; verbose={}", root.display(), target, dest.display(), deps.display(), verbose); - let rustc = prepare_rustc(root, target, dest, deps); + let crate_types = target.rustc_crate_types(); - try!((if verbose { - rustc.exec() - } else { - rustc.exec_with_output().and(Ok(())) - }).map_err(|e| rustc_to_cargo_err(rustc.get_args().as_slice(), root, e))); + for crate_type in crate_types.iter() { + log!(5, "root={}; target={}; crate_type={}; dest={}; deps={}; verbose={}", + root.display(), target, crate_type, dest.display(), deps.display(), verbose); + + let rustc = prepare_rustc(root, target, *crate_type, dest, deps); + + try!((if verbose { + rustc.exec() + } else { + rustc.exec_with_output().and(Ok(())) + }).map_err(|e| rustc_to_cargo_err(rustc.get_args().as_slice(), root, e))); + } Ok(()) } -fn prepare_rustc(root: &Path, target: &Target, dest: &Path, deps: &Path) -> ProcessBuilder { +fn prepare_rustc(root: &Path, target: &Target, crate_type: &'static str, dest: &Path, deps: &Path) -> ProcessBuilder { let mut args = Vec::new(); - build_base_args(&mut args, target, dest); + build_base_args(&mut args, target, crate_type, dest); build_deps_args(&mut args, deps); util::process("rustc") @@ -77,11 +83,11 @@ fn prepare_rustc(root: &Path, target: &Target, dest: &Path, deps: &Path) -> Proc .env("RUST_LOG", None) // rustc is way too noisy } -fn build_base_args(into: &mut Args, target: &Target, dest: &Path) { +fn build_base_args(into: &mut Args, target: &Target, crate_type: &'static str, dest: &Path) { // TODO: Handle errors in converting paths into args into.push(target.get_path().display().to_str()); into.push("--crate-type".to_str()); - into.push(target.rustc_crate_type().to_str()); + into.push(crate_type.to_str()); into.push("--out-dir".to_str()); into.push(dest.display().to_str()); } diff --git a/src/cargo/sources/git/source.rs b/src/cargo/sources/git/source.rs index a3872be8e..12c68af8b 100644 --- a/src/cargo/sources/git/source.rs +++ b/src/cargo/sources/git/source.rs @@ -37,6 +37,7 @@ impl Show for GitSource { impl Source for GitSource { fn update(&self) -> CargoResult<()> { + println!("Updating git repository `{}`", self.remote.get_url()); log!(5, "updating git source `{}`", self.remote); let repo = try!(self.remote.checkout(&self.db_path)); try!(repo.copy_to(self.reference.as_slice(), &self.checkout_path)); diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index bb05837cf..57f1f67b1 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -5,6 +5,7 @@ use std::collections::HashMap; use serialize::Decodable; use core::source::{SourceId,GitKind}; +use core::manifest::{LibKind,Lib}; use core::{Summary,Manifest,Target,Dependency,PackageId}; use util::{CargoResult,Require,simple_human,toml_error}; @@ -159,6 +160,7 @@ impl TomlManifest { #[deriving(Decodable,Encodable,PartialEq,Clone,Show)] struct TomlTarget { name: String, + crate_type: Option>, path: Option } @@ -168,7 +170,8 @@ fn normalize(lib: Option<&[TomlLibTarget]>, bin: Option<&[TomlBinTarget]>) -> Ve fn lib_targets(dst: &mut Vec, libs: &[TomlLibTarget]) { let l = &libs[0]; let path = l.path.clone().unwrap_or_else(|| format!("src/{}.rs", l.name)); - dst.push(Target::lib_target(l.name.as_slice(), &Path::new(path))); + let crate_types = l.crate_type.clone().and_then(|kinds| LibKind::from_strs(kinds).ok()).unwrap_or_else(|| vec!(Lib)); + dst.push(Target::lib_target(l.name.as_slice(), crate_types, &Path::new(path))); } fn bin_targets(dst: &mut Vec, bins: &[TomlBinTarget], default: |&TomlBinTarget| -> String) { -- 2.30.2